package com.caocaog.market.finance.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.caocaog.market.finance.entity.FinanceGroup;
import com.caocaog.market.finance.service.impl.FinanceGroupServiceImpl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

import static com.caocaog.market.finance.enums.WithdrawStatus.Type.GROUP;
import static com.caocaog.market.finance.enums.WithdrawStatus.Type.LINE;
import static java.util.stream.Collectors.toSet;

@Getter
public enum WithdrawStatus {

    /**
     * 待提现
     * line有这个状态，group没有，因为group初始状态就是待审核
     */
    PENDING_WITHDRAWAL("待提现", 0, 0, LINE),

    /**
     * 待审核
     */
    TO_BE_REVIEWED("待审核", 1, 0, LINE, GROUP),

    /**
     * 待转账
     */
    PENDING_TRANSFER("待转账", 2, 1, LINE, GROUP),

    /**
     * 已提现
     */
    FULLY_WITHDRAW("已提现", 3, 2, LINE, GROUP),

    /**
     * 驳回
     * group有这个状态，line没有（驳回后，group状态变为驳回，line状态变为待提现）
     */
    REJECT("驳回", -1, 1, GROUP),

    /**
     * 转账失败
     * group有这个状态，line没有（转账失败后，group状态变为转账失败，line状态不变还是待转账）
     */
    TRANSFER_FAILED("转账失败", -2, 2, GROUP);

    private final String name;
    @EnumValue
    @JsonValue
    private final Integer code;
    /**
     * 提现状态是个链式流程，这个字段表示当前状态的上一个状态，用于判断是否可以修改（待提现0不参与链式流程）
     * <p>1. 待审核 -> 待转账 -> 已提现</p>
     * <p>2. 待审核 -> 待转账 -> 转账失败</p>
     * <p>3. 待审核 -> 驳回</p>
     * <p>4. 转账失败 -> 转账失败</p>
     * <p>5. 转账失败 -> 已提现</p>
     */
    private final Integer lastCode;

    private final Set<Type> types;

    WithdrawStatus(String name, int code, int lastCode, Type... types) {
        this.name = name;
        this.code = code;
        this.lastCode = lastCode;
        this.types = Stream.of(types).collect(toSet());
    }

    /**
     * 校验是否可以修改，用于{@link FinanceGroupServiceImpl#changeFinanceGroupStatus(FinanceGroup, WithdrawStatus, WithdrawStatus, String) 更改提现集状态}
     * 详情见{@link WithdrawStatus#lastCode}注释
     */
    public boolean canUpdate(WithdrawStatus lastStatus) {
        if (Objects.equals(this.code, PENDING_WITHDRAWAL.code)) return true; // 待提现0不校验
        if (Objects.equals(lastStatus.code, TRANSFER_FAILED.code)) { // 已提现（「已提现」的lastCode存放的是「待转账」，直接判断lastCode是不行的，所以「转账失败」状态需要特殊处理）
            if (Objects.equals(this.code, TRANSFER_FAILED.code)) return true; // 4. 转账失败 -> 转账失败
            if (Objects.equals(this.code, FULLY_WITHDRAW.code)) return true; // 5. 转账失败 -> 已提现
        }
        return this.lastCode.equals(lastStatus.getCode()); // 其他状态校验（1、2、3）
    }


    @JsonCreator
    public static WithdrawStatus match(int status) {
        return Stream.of(WithdrawStatus.values())
                .filter(s -> s.getCode().equals(status))
                .findAny()
                .orElseThrow(() -> new IllegalArgumentException("未知的提现状态"));
    }

    public enum Type {
        LINE, GROUP
    }


}
